#pragma once 
#include <iostream>
#include <vector>
#include <semaphore.h>
#include <pthread.h>
namespace cp_roundQueue{
  const int g_cap_default = 10;
  template<class T>
    class RoundQueue{
      private:
        std::vector<T> round_queue_;//用数组模拟环形队列
        int cap_;//环形队列的容量
        sem_t blank_sem_;//生产者关心的空位置的资源
        sem_t data_sem_;//消费者关心的数据位置的资源

        pthread_mutex_t c_mtx;//消费者的互斥锁
        pthread_mutex_t p_mtx;//生产者的互斥锁

        int c_index_;//生产者的位置下标
        int p_index_;//消费者的位置下标
      public:
        RoundQueue(int cap = g_cap_default): round_queue_(cap), cap_(cap){
          sem_init(&blank_sem_, 0, cap);
          sem_init(&data_sem_, 0, 0);
          pthread_mutex_init(&c_mtx, nullptr);
          pthread_mutex_init(&p_mtx, nullptr);
          c_index_ = p_index_ = 0;
        }
        ~RoundQueue(){
          sem_destroy(&blank_sem_);
          sem_destroy(&data_sem_);
          pthread_mutex_destroy(&c_mtx);
          pthread_mutex_destroy(&p_mtx);
        }

        void push(const T& in){
          sem_wait(&blank_sem_);//申请空位置的信号量
          pthread_mutex_lock(&c_mtx);

          round_queue_[p_index_] = in;
          p_index_++;
          p_index_ %= cap_;

          pthread_mutex_unlock(&c_mtx);
          sem_post(&data_sem_);//发布数据位置的信号量
        }
        void pop(T* out){
          sem_wait(&data_sem_);//申请数据位置的信号量
          pthread_mutex_lock(&p_mtx);

          *out = round_queue_[c_index_];
          c_index_++;
          c_index_ %= cap_;

          pthread_mutex_unlock(&p_mtx);
          sem_post(&blank_sem_);//发布空位置的信号量
        }
    };
}
